package com.humble.humbleojjudgeservice.judge;/*
  humble keep gonging
*/


import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.humble.humbleojcommon.common.ErrorCode;
import com.humble.humbleojcommon.exception.BusinessException;
import com.humble.humbleojjudgeservice.judge.codeSandbox.SandboxFactory;
import com.humble.humbleojjudgeservice.judge.codeSandbox.SandboxProxy;
import com.humble.humbleojmodel.model.codeSandbox.ExecuteCodeRequest;
import com.humble.humbleojmodel.model.codeSandbox.ExecuteCodeResponse;
import com.humble.humbleojmodel.model.dto.Question.JudgeCase;
import com.humble.humbleojmodel.model.dto.Question.JudgeConfig;
import com.humble.humbleojmodel.model.dto.QuestionSubmit.JudgeInfo;
import com.humble.humbleojmodel.model.entity.Question;
import com.humble.humbleojmodel.model.entity.QuestionSubmit;
import com.humble.humbleojmodel.model.judge.JudgeContext;
import com.humble.humbleojmodel.model.judge.JudgeResult;
import com.humble.humbleojmodel.model.vo.QuestionSubmitVO;
import com.humble.humbleojserviceclient.service.QuestionFeignClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.List;

import static com.humble.humbleojmodel.model.enums.QuestionSubmitStatusEnum.*;

@Service
public class JudgeServiceImpl implements JudgeService {
    @Value("${codeSandbox.type}")
    private String type;

    @Resource
    QuestionFeignClient questionFeignClient;

    @Resource
    private SandboxFactory sandboxFactory;

    @Override
    public void doJudgeService(Long questionSubmitId) throws Exception {
        if (questionSubmitId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "判题模块中未获取到submitId");
        }
        //获得提交信息
        QuestionSubmit questionSubmitById = questionFeignClient.getSubmitById(questionSubmitId);
        if (questionSubmitById == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "判题模块在获取题目提交时出现错误");
        }
        QuestionSubmitVO questionSubmitVO = QuestionSubmitVO.objToVo(questionSubmitById);
        Integer status = questionSubmitVO.getStatus();
        if (status.equals(WAITING.getValue())) {
            QuestionSubmit questionSubmit = new QuestionSubmit();
            questionSubmit.setId(questionSubmitId);
            questionSubmit.setStatus(RUNNING.getValue());
            questionFeignClient.updateSubmit(questionSubmit);
        } else {
            return;
        }
        //获得具体参数
        String code = questionSubmitVO.getCode();
        String language = questionSubmitVO.getLanguage();
        Long questionId = questionSubmitVO.getQuestionId();

        //根据questionId获得问题
        Question questionById = questionFeignClient.getById(questionId);
        String judgeCaseStr = questionById.getJudgeCase();
        List<JudgeCase> list = JSONUtil.toList(judgeCaseStr, JudgeCase.class);
        ArrayList<String> inputList = new ArrayList<>();
        ArrayList<String> standardOutputList = new ArrayList<>();
        for (JudgeCase judgeCase : list) {
            inputList.add(judgeCase.getInput());
            standardOutputList.add(judgeCase.getOutput());
        }
        ExecuteCodeRequest executeCodeRequest = new ExecuteCodeRequest(code, inputList, language);
        ExecuteCodeResponse executeCodeResponse = new SandboxProxy(sandboxFactory.newInstance(type)).executeCode(executeCodeRequest);

        //调用判题模块
        if(executeCodeResponse==null){
            JudgeInfo judgeInfo = new JudgeInfo();
            judgeInfo.setMessage("判题模块出错");
            String judgeStr = JSONUtil.toJsonStr(judgeInfo);

            QuestionSubmit questionSubmit = new QuestionSubmit();
            questionSubmit.setId(questionSubmitId);
            questionSubmit.setJudgeInfo(judgeStr);
            questionSubmit.setStatus(FAILURE.getValue());
            questionFeignClient.updateSubmit(questionSubmit);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"判题模块有误！");
        }
        //使用策略模式完成判题；
        JudgeContext judgeContext = new JudgeContext();
        judgeContext.setQuestionSubmitId(questionSubmitId);
        judgeContext.setLanguage(language);
        judgeContext.setStandardOutputList(standardOutputList);
        judgeContext.setOutputList(executeCodeResponse.getOutputList());
        judgeContext.setJudgeConfig(JSONUtil.toBean(questionById.getJudgeConfig(), JudgeConfig.class));
        judgeContext.setJudgeInfo(executeCodeResponse.getJudgeInfo());
        judgeContext.setResponseStatus(executeCodeResponse.getStatus());
        judgeContext.setExecuteCodeErrorMessage(executeCodeResponse.getMessage());

        //判题模块获取结果
        JudgeResult judgeResult = new JudgeManager().useJudgeStrategy(judgeContext);

        //更新题目的通过人数和提交人数
        Question question = new Question();
        question.setId(questionId);
        if(judgeResult.getJudgeStatus()==2){
            question.setAcceptedNum(questionById.getAcceptedNum()+1);
        }
        question.setSubmitNum(questionById.getSubmitNum()+1);
        questionFeignClient.update(question);


        //修改题目提交表的信息
        QuestionSubmit questionSubmit = new QuestionSubmit();
        questionSubmit.setId(questionSubmitId);
        questionSubmit.setStatus(judgeResult.getJudgeStatus());
        String judgeInfoJson = JSONUtil.toJsonStr(judgeResult.getJudgeInfo());
        questionSubmit.setJudgeInfo(judgeInfoJson);
        questionFeignClient.updateSubmit(questionSubmit);
    }
}
